package com.yfq.springframework.xml;

import com.yfq.springframework.beans.PropertyValue;
import com.yfq.springframework.beans.config.BeanDefinition;
import com.yfq.springframework.beans.config.BeanReference;
import com.yfq.springframework.support.AbstractBeanDefinitionReader;
import com.yfq.springframework.support.BeanDefinitionRegistry;
import com.yfq.springframework.core.io.Resource;
import com.yfq.springframework.core.io.ResourceLoader;
import com.yfq.springframework.util.StrUtils;
import org.dom4j.*;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @author 姚凤桥
 * @date 2022/12/12 16:16
 * @description
 */
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    public XmlBeanDefinitionReader(BeanDefinitionRegistry beanDefinitionRegistry, ResourceLoader resourceLoader) {
        super(beanDefinitionRegistry, resourceLoader);
    }

    @Override
    public void loadBeanDefinitions(Resource resource) throws IOException {
        InputStream is = resource.getInputStream();
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(is);
            Element root = document.getRootElement();
            if (root == null) {
                return;
            }

            List<Element> elements = root.elements("bean");
            for (Element bean : elements) {
                String id = getStringAttribute(bean, "id");
                String name = getStringAttribute(bean, "name");
                String beanClass = getStringAttribute(bean, "class");

                Class<?> clazz = Class.forName(beanClass);
                //根据优先级来确定beanName,id > name
                String beanName = !StrUtils.isEmpty(id) ? id : name;
                if (StrUtils.isEmpty(beanName)) {
                    beanName = clazz.getSimpleName();
                }

                BeanDefinition beanDefinition = new BeanDefinition(clazz);
                //读取property标签
                List<Element> properties = bean.elements("property");
                for (Element property : properties) {
                    String propertyName = getStringAttribute(property, "name");
                    String propertyValue = getStringAttribute(property, "value");
                    String propertyRef = getStringAttribute(property, "ref");

                    //如果ref属性不为空，优先使用ref
                    Object value = StrUtils.isEmpty(propertyRef) ? propertyValue : new BeanReference(propertyRef);

                    beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(propertyName, value));
                }

                //注册beanDefinition
                if (getRegistry().containsBeanName(beanName)) {
                    throw new RuntimeException("重复的beanName：" + beanName);
                }

                getRegistry().registerBeanDefinition(beanName, beanDefinition);
            }
        } catch (DocumentException | ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void loadBeanDefinitions(Resource... resource) throws IOException {
        if (resource != null) {
            for (Resource res : resource) {
                loadBeanDefinitions(res);
            }
        }
    }

    @Override
    public void loadBeanDefinitions(String location) throws IOException {
        ResourceLoader resourceLoader = getResourceLoader();
        Resource resource = resourceLoader.getResource(location);
        loadBeanDefinitions(resource);
    }

    private String getStringAttribute(Element element, String name) {
        Attribute attribute = element.attribute(name);
        if (attribute == null) {
            return null;
        }

        return attribute.getStringValue();
    }

}
